package com.ozo.boot.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ozo.boot.common.base.constant.StatusEnum;
import com.ozo.boot.common.core.exception.ServiceException;
import com.ozo.boot.manage.exception.ManageExceptionEnum;
import com.ozo.boot.manage.pojo.vo.SysPermissionTreeVO;
import com.ozo.boot.manage.pojo.vo.SysPermissionVO;
import com.ozo.boot.common.base.constant.MenuTypeEnum;
import com.ozo.boot.common.base.model.BaseBatchDTO;
import com.ozo.boot.common.satoken.context.UserLoginHelper;
import com.ozo.boot.manage.pojo.dto.ChangeStatusDTO;
import com.ozo.boot.manage.pojo.dto.SysPermissionQueryDTO;
import com.ozo.boot.manage.pojo.dto.SysPermissionSaveDTO;
import com.ozo.boot.manage.entity.SysPermission;
import com.ozo.boot.manage.entity.SysRolePermissionRel;
import com.ozo.boot.manage.entity.SysUserRoleRel;
import com.ozo.boot.manage.mapper.SysPermissionMapper;
import com.ozo.boot.manage.service.ISysPermissionService;
import com.ozo.boot.manage.service.ISysRolePermissionRelService;
import com.ozo.boot.manage.service.ISysUserRoleRelService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author qiangesoft
 * @since 2024-07-11
 */
@RequiredArgsConstructor
@Service
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements ISysPermissionService {

    private final ISysUserRoleRelService sysUserRoleRelService;

    private final ISysRolePermissionRelService sysRolePermissionRelService;

    @Override
    public void add(SysPermissionSaveDTO saveDTO) {
        // 参数校验
        String type = saveDTO.getType();
        if (MenuTypeEnum.MENU.getCode().equals(type)) {
            String route = saveDTO.getRoute();
            String component = saveDTO.getComponent();
            if (StrUtil.isBlank(route) || StrUtil.isBlank(component)) {
                throw new ServiceException(ManageExceptionEnum.MENU_ROUTE_COMPONENT_NOT_EMPTY);
            }
        }
        SysPermission sysPermission = BeanUtil.copyProperties(saveDTO, SysPermission.class);
        baseMapper.insert(sysPermission);
    }

    @Override
    public void remove(BaseBatchDTO<Long> batchDTO) {
        baseMapper.deleteBatchIds(batchDTO.getIdList());
    }

    @Override
    public void edit(SysPermissionSaveDTO saveDTO) {
        // 参数校验
        String type = saveDTO.getType();
        if (MenuTypeEnum.MENU.getCode().equals(type)) {
            String route = saveDTO.getRoute();
            String component = saveDTO.getComponent();
            if (StrUtil.isBlank(route) || StrUtil.isBlank(component)) {
                throw new ServiceException(ManageExceptionEnum.MENU_ROUTE_COMPONENT_NOT_EMPTY);
            }
        }
        SysPermission sysPermission = BeanUtil.copyProperties(saveDTO, SysPermission.class);
        baseMapper.updateById(sysPermission);
    }

    @Override
    public List<SysPermissionVO> list(SysPermissionQueryDTO queryDTO) {
        List<SysPermissionVO> permissionVOList = new ArrayList<>();

        LambdaQueryWrapper<SysPermission> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(queryDTO.getType()), SysPermission::getType, queryDTO.getType())
                .like(StrUtil.isNotBlank(queryDTO.getTitle()), SysPermission::getTitle, queryDTO.getTitle())
                .eq(StrUtil.isNotBlank(queryDTO.getStatus()), SysPermission::getStatus, queryDTO.getStatus())
                .orderByAsc(SysPermission::getOrderNum)
                .orderByAsc(SysPermission::getId);
        List<SysPermission> permissionList = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(permissionList)) {
            return permissionVOList;
        }

        permissionVOList = BeanUtil.copyToList(permissionList, SysPermissionVO.class);

        for (SysPermissionVO sysPermissionVO : permissionVOList) {
            List<SysPermissionVO> childrenList = permissionVOList.stream().filter(e -> sysPermissionVO.getId().equals(e.getParentId())).collect(Collectors.toList());
            sysPermissionVO.setChildren(childrenList);
        }
        return permissionVOList.stream().filter(e -> e.getParentId() == null).collect(Collectors.toList());
    }

    @Override
    public void changeStatus(ChangeStatusDTO statusDTO) {
        LambdaUpdateWrapper<SysPermission> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SysPermission::getId, statusDTO.getId())
                .set(SysPermission::getStatus, statusDTO.getStatus());
        baseMapper.update(updateWrapper);
    }

    @Override
    public List<SysPermissionVO> listPermissionByUserId(Long userId) {
        return this.listByUserId(userId, List.of(MenuTypeEnum.BUTTON.getCode()));
    }

    @Override
    public List<SysPermissionTreeVO> oneself() {
        List<SysPermissionTreeVO> permissionTreeVOList = new ArrayList<>();

        Long userId = UserLoginHelper.getUserId();

        List<SysPermissionVO> permissionVOList = this.listByUserId(userId, null);
        if (CollectionUtils.isEmpty(permissionVOList)) {
            return permissionTreeVOList;
        }

        List<Long> permissionIdList = permissionVOList.stream().map(SysPermissionVO::getId).collect(Collectors.toList());
        LambdaQueryWrapper<SysPermission> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysPermission::getStatus, StatusEnum.ENABLE.getCode())
                .in(SysPermission::getId, permissionIdList)
                .in(SysPermission::getType, MenuTypeEnum.MENU.getCode(), MenuTypeEnum.IFRAME.getCode(), MenuTypeEnum.LINK.getCode())
                .orderByAsc(SysPermission::getOrderNum);
        List<SysPermission> sysPermissionList = baseMapper.selectList(queryWrapper);
        for (SysPermission sysPermission : sysPermissionList) {
            SysPermissionTreeVO permissionTreeVO = new SysPermissionTreeVO();
            permissionTreeVO.setId(sysPermission.getId());
            permissionTreeVO.setParentId(sysPermission.getParentId());
            permissionTreeVO.setName(sysPermission.getCode());
            permissionTreeVO.setPath(sysPermission.getRoute());
            permissionTreeVO.setComponent(sysPermission.getComponent());
            SysPermissionTreeVO.Meta meta = new SysPermissionTreeVO.Meta();
            meta.setTitle(sysPermission.getTitle());
            meta.setIcon(sysPermission.getIcon());
            meta.setType(sysPermission.getType());
            meta.setAffix(sysPermission.getAffix());
            meta.setHidden(sysPermission.getHidden());
            permissionTreeVO.setMeta(meta);
            permissionTreeVOList.add(permissionTreeVO);
        }

        this.buildTree(permissionTreeVOList);
        return permissionTreeVOList.stream().filter(e -> e.getParentId() == null).collect(Collectors.toList());
    }

    /**
     * 构建树
     *
     * @param permissionTreeVOList
     */
    private void buildTree(List<SysPermissionTreeVO> permissionTreeVOList) {
        for (SysPermissionTreeVO sysPermissionVO : permissionTreeVOList) {
            List<SysPermissionTreeVO> childrenList = permissionTreeVOList.stream().filter(e -> sysPermissionVO.getId().equals(e.getParentId())).collect(Collectors.toList());
            sysPermissionVO.setChildren(childrenList);
        }
    }

    /**
     * 查询用户的菜单权限
     *
     * @param userId
     * @param typeList
     * @return
     */
    private List<SysPermissionVO> listByUserId(Long userId, List<String> typeList) {
        List<SysPermissionVO> permissionVOList = new ArrayList<>();

        List<SysUserRoleRel> userRoleRelList = sysUserRoleRelService.lambdaQuery().eq(SysUserRoleRel::getUserId, userId).list();
        if (userRoleRelList.isEmpty()) {
            return permissionVOList;
        }

        Set<Long> roleIdSet = userRoleRelList.stream().map(SysUserRoleRel::getRoleId).collect(Collectors.toSet());
        List<SysRolePermissionRel> sysRolePermissionRelList = sysRolePermissionRelService.lambdaQuery().in(SysRolePermissionRel::getRoleId, roleIdSet).list();
        if (sysRolePermissionRelList.isEmpty()) {
            return permissionVOList;
        }

        Set<Long> permissionIdList = sysRolePermissionRelList.stream().map(SysRolePermissionRel::getPermissionId).collect(Collectors.toSet());
        List<SysPermission> sysPermissionList = this.lambdaQuery()
                .eq(SysPermission::getStatus, StatusEnum.ENABLE.getCode())
                .in(SysPermission::getId, permissionIdList)
                .in(CollUtil.isNotEmpty(typeList), SysPermission::getType, typeList).list();
        permissionVOList = BeanUtil.copyToList(sysPermissionList, SysPermissionVO.class);

        return permissionVOList;
    }

}
